package com.piece.blog.service;

import com.piece.blog.model.BlogGrepDefine;
import com.piece.blog.repository.BlogGrepDefineRepository;
import com.piece.core.framework.enums.OptionType;
import com.piece.core.framework.enums.sql.SqlKey;
import com.piece.core.framework.support.bootstrap.Order;
import com.piece.core.framework.support.bootstrap.TreeData;
import com.piece.core.framework.support.convert.Convert;
import com.piece.core.framework.util.string.StringUtil;
import com.piece.core.jpa.repository.BaseService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.PostConstruct;
import javax.annotation.Resource;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Slf4j
@Service
@Transactional
public class BlogGrepDefineService extends BaseService<BlogGrepDefine, Long> {

    @Resource
    private JdbcTemplate jdbcTemplate;

    @Resource
    private BlogGrepDefineRepository blogGrepDefineRepository;

    @PostConstruct
    public void initRepository() {
        setRepository(blogGrepDefineRepository);
    }

    /**
     * 新增规则信息
     */
    @Override
    public BlogGrepDefine insert(BlogGrepDefine dict) {
        if (0 != dict.getParentCode()) {
            BlogGrepDefine info = blogGrepDefineRepository.findById(dict.getParentCode());
            if (StringUtil.isEmpty(info.getAncestors())) {
                dict.setAncestors(Convert.toStr(dict.getParentCode(), "0"));
            } else {
                dict.setAncestors(info.getAncestors() + "," + dict.getParentCode());
            }
        } else {
            dict.setAncestors(null);
        }
        return blogGrepDefineRepository.insert(dict);
    }

    /**
     * 更新字典信息
     */
    @Override
    public void update(BlogGrepDefine dict) {
        BlogGrepDefine info = blogGrepDefineRepository.findById(dict.getParentCode());
        if (null != info) {
            String ancestors = Convert.toStr(dict.getParentCode());
            if (StringUtil.isEmpty(info.getAncestors())) {
                if ("0".equals(ancestors)) {
                    ancestors = null;
                }
            } else {
                ancestors = info.getAncestors() + "," + info.getDictCode();
            }
            dict.setAncestors(ancestors);
        }
        blogGrepDefineRepository.update(dict);
    }

    /**
     * 删除字典
     */
    @Override
    public void delete(Serializable dictCode) {
        BlogGrepDefine define = blogGrepDefineRepository.findById(dictCode);
        if (OptionType.OPTION.getCode().equals(define.getDictGroup())) {
            blogGrepDefineRepository.delete(dictCode);
        } else {
            String sql = "delete from BlogGrepDefine where dictGroup = ?0";
            blogGrepDefineRepository.executeHql(sql, new Object[]{define.getDictGroup()});
        }
    }

    /**
     * 批量删除字典
     */
    @Override
    public int delete(Serializable[] ids) {
        int i = 0;
        for (Serializable id : ids) {
            delete(id);
            i++;
        }
        return i;
    }

    /**
     * 查询所有
     */
    public List<BlogGrepDefine> findAll() {
        return blogGrepDefineRepository.findByCondition(null, generateDefaultOrder());
    }

    /**
     * 根据字典组名查询字典选项
     *
     * @param dictGroup 定义组名
     */
    public List<BlogGrepDefine> findByDicGroup(String dictGroup) {
        return findByDicGroup(dictGroup, true);
    }

    /**
     * 根据字典组名查询字典数据
     *
     * @param dictGroup 定义组名
     * @param onlyOption 是否只返回选项数据
     * @return 字典数据集合信息
     */
    public List<BlogGrepDefine> findByDicGroup(String dictGroup, boolean onlyOption) {
        HashMap<String, Object> condition = new HashMap<>();
        condition.put("dictGroup", dictGroup);
        if (onlyOption) {
            condition.put("dictType", OptionType.OPTION.getCode());
        }
        return blogGrepDefineRepository.findByCondition(condition, generateDefaultOrder());
    }

    /**
     * 根据所有字典组（不包含字典选项）
     */
    public List<BlogGrepDefine> findByDicParent() {
        HashMap<String, Object> condition = new HashMap<>();
        condition.put("dictType", OptionType.GROUP.getCode());
        return blogGrepDefineRepository.findByCondition(condition, generateDefaultOrder());
    }

    /**
     * 根据字典类型和字典键值查询字典数据信息
     *
     * @param dictGroup 字典组名
     * @param dictValue 字典键值
     */
    public BlogGrepDefine findByGroupValue(String dictGroup, String dictValue) {
        HashMap<String, Object> condition = new HashMap<>();
        condition.put("dictGroup", dictGroup);
        condition.put("dictValue", dictValue);
        return blogGrepDefineRepository.findOneByCondition(condition);
    }

    /**
     * 根据字典类型和字典键值查询字典数据信息
     *
     * @param dictGroup 字典组名
     * @param dictLabel 字典标签
     */
    public BlogGrepDefine findByGroupLabel(String dictGroup, String dictLabel) {
        HashMap<String, Object> condition = new HashMap<>();
        condition.put("dictGroup", dictGroup);
        condition.put("dictLabel", dictLabel);
        return blogGrepDefineRepository.findOneByCondition(condition);
    }

    /**
     * 根据字典类型和字典键值查询字典数据信息
     *
     * @param dictGroup 字典组名
     */
    public BlogGrepDefine findByGroup(String dictGroup) {
        HashMap<String, Object> condition = new HashMap<>();
        condition.put("dictGroup", dictGroup);
        condition.put("dictType", OptionType.GROUP.getCode());
        return blogGrepDefineRepository.findOneByCondition(condition);
    }

    /**
     * 根据字典类型和字典键值查询字典数据信息
     *
     * @param dictGroup 字典组名
     * @param dictValue 字典键值
     */
    public List<BlogGrepDefine> findByGroupValue(String dictGroup, List<String> dictValue) {
        HashMap<String, Object> condition = new HashMap<>();
        condition.put("dictGroup", dictGroup);
        condition.put("Q_dictValue_S_IN", dictValue);
        return blogGrepDefineRepository.findByCondition(condition, generateDefaultOrder());
    }

    /**
     * 查询字典树
     */
    public List<TreeData> findTreeData() {
        List<BlogGrepDefine> dictList = findAll();
        return findTreeData(dictList);
    }

    /**
     * 对象转字典树
     */
    public List<TreeData> findTreeData(List<BlogGrepDefine> dictList) {
        List<TreeData> trees = new ArrayList<>();
        for (BlogGrepDefine dict : dictList) {
            TreeData treeData = TreeData.builder()
                            .id(String.valueOf(dict.getDictCode()))
                            .pId(String.valueOf(dict.getParentCode()))
                            .title(dict.getDictLabel())
                            .name(dict.getDictLabel())
                            .build();
            trees.add(treeData);
        }
        return trees;
    }

    /**
     * 获取下一个字典序号
     *
     * @param dict
     */
    public Long findNextDictSort(BlogGrepDefine dict) {
        String sql = "select ifnull(max(dict_sort) + 1,1) from blog_grep_define where parent_code = " + dict.getParentCode() ;
        return jdbcTemplate.queryForObject(sql, Long.class);
    }

    public void updateGrepRule(String group, Map<String, Object> grepRule) throws Exception {
        String grep_image_define = (String) grepRule.get("grep_image_define");
        String grep_title_define = (String) grepRule.get("grep_title_define");
        String grep_download_define = (String) grepRule.get("grep_download_define");
        String grep_content_define = (String) grepRule.get("grep_content_define");

        BlogGrepDefine parent = findByGroup(group);
        if (null == parent) {
            parent = new BlogGrepDefine();
            generateDefault(parent, group);
            parent = insert(parent);
        }

        updateGrepRule(group, "grep_image_define", grep_image_define, parent);
        updateGrepRule(group, "grep_title_define", grep_title_define, parent);
        updateGrepRule(group, "grep_download_define", grep_download_define, parent);
        updateGrepRule(group, "grep_content_define", grep_content_define, parent);
    }

    private void updateGrepRule(String group, String label, String value, BlogGrepDefine parent) throws Exception {
        BlogGrepDefine define = findByGroupLabel(group, label);
        if (null != define) {
            define.setDictValue(value);
        } else {
            define = generateDefault(parent);
            define.setDictValue(value);
            define.setDictLabel(label);
        }
        insertOrUpdate(define);
    }

    private BlogGrepDefine generateDefault(BlogGrepDefine parent) {
        BlogGrepDefine define = new BlogGrepDefine();
        define.setParentCode(parent.getDictCode());
        define.setDictGroup(parent.getDictGroup());
        define.setDictType(OptionType.OPTION.getCode());
        define.setIsLeaf(OptionType.LEAF.getCode());
        define.setDictSort(findNextDictSort(define));
        return define;
    }

    private void generateDefault(BlogGrepDefine parent, String group) {
        parent.setParentCode(0l);
        parent.setDictGroup(group);
        parent.setDictType(OptionType.GROUP.getCode());
        parent.setIsLeaf(OptionType.NOT_LEAF.getCode());
        parent.setDictSort(findNextDictSort(parent));
    }

    protected List<Order> generateDefaultOrder() {
        List<Order> orders = new ArrayList<>();
        orders.add(new Order("dictSort", SqlKey.ASC));
        return orders;
    }
}
